package example.designpattern.fsm;


import example.designpattern.fsm.event.AbstractEvent;
import example.designpattern.fsm.listener.Listener;
import example.designpattern.fsm.listener.TransitionListener;
import example.designpattern.fsm.state.AbstractState;
import example.designpattern.fsm.transition.StateTransition;
import example.designpattern.fsm.transition.StateTransitionBuilder;
import java.util.ArrayList;
import java.util.List;

/**
 * 状态机模式
 */
public class StateMachine extends StateTransitionBuilder {

  protected final List<StateTransition> stateTransitions = new ArrayList<>();

  protected final List<Listener> listeners = new ArrayList<>();

  protected StateContext stateContext;

  public StateMachine(AbstractState initState) {

    this(initState, null);
  }

  public StateMachine(AbstractState initState, AbstractEvent initEvent) {

    this.stateContext = new StateContext(initState, initEvent, this);
  }

  public void submit(AbstractEvent event) {

    if (event == null) {
      return;
    }
    this.stateContext.setCurrentEvent(event);
    notifyListener(event);
    for (StateTransition stateTransition : this.stateTransitions) {
      stateTransition.transition(this.stateContext);
    }
  }

  public void notifyListener(AbstractEvent event) {

    for (Listener listener : listeners) {
      if (listener.supportType(event.getClass())) {
        listener.onEvent(event, this.stateContext);
      }
    }
  }

  public void addStateTransition(StateTransition stateTransition) {

    this.stateTransitions.add(stateTransition);
  }


  public void addListener(Listener listener) {

    this.listeners.add(listener);
  }

  public void addTransitionListener(TransitionListener listener) {

    this.stateContext.getTransitionListeners().add(listener);
  }

  @Override
  public StateTransition build() {

    StateTransition stateTransition = new StateTransition(this);
    this.stateTransitions.add(stateTransition);
    return stateTransition;
  }

}